<template>
  <div class="textarea" :class="`${statusClass} ${disabledClass}`" :style="style">
    <div class="textarea-header" :class="disabledClass"><slot></slot></div>
    <textarea
      class="textarea-dom"
      :class="disabledClass"
      ref="textareaDom"
      :value="props.modelValue"
      :placeholder="props.placeholder"
      :disabled="disabled"
      @input="inputTextareaValue"
      @focus="inputFocus"
      @blur="inputBlur"
    >
    </textarea>
    <transition name="translateTextY" mode="out-in">
      <div v-if="errorMessage" class="textarea-message">
        {{ errorMessage }}
      </div>
    </transition>
    <i v-if="clearable" class="iconfont iconcha textarea-del" @click="clearValue"></i>
  </div>
</template>

<script setup lang="ts">
import { computed, defineEmits, defineProps, watch, ref, nextTick } from 'vue'

type TTextarea = {
  modelValue: string
  width?: number | string
  height?: number | string
  placeholder?: string
  validator?: () => Promise<string | void>
  clearable?: boolean
  disabled?: boolean
}

const emit = defineEmits(['update:modelValue', 'input', 'focus', 'blur'])
const props = defineProps<TTextarea>()

const textareaDom = ref<HTMLInputElement>()
const isFocus = ref<boolean>(false)
const errorMessage = ref<string>('')

/**
 * 清楚textarea中的值
 */
const clearValue = () => {
  emit('update:modelValue', '')
}

/**
 * 样式格式化
 */
const style = computed(() => {
  const w = typeof props.width === 'string' ? props.width : `${props.width}px`
  const h = typeof props.height === 'string' ? props.height : `${props.height}px`
  return { width: w, height: h }
})

/**
 * 当前边框样式绑定
 */
const statusClass = computed(() => {
  if (errorMessage.value) {
    return 'textarea-border-error'
  } else if (isFocus.value) {
    return 'textarea-border-active'
  }
})

/**
 * 当前可用状态样式绑定
 */
const disabledClass = computed(() => {
  if (props.disabled) {
    // 禁用
    return 'textarea-disabled'
  } else {
    return undefined
  }
})

/**
 * textarea输入回调
 */
const inputTextareaValue = () => {
  nextTick(() => {
    if (props.validator) {
      props
        .validator()
        .then(() => {
          errorMessage.value = ''
        })
        .catch((e) => {
          errorMessage.value = typeof e === 'string' ? e : ''
        })
    }
  })

  emit('update:modelValue', textareaDom.value?.value)
  emit('input', textareaDom.value?.value)
}

/**
 * textarea聚焦回调
 */
const inputFocus = () => {
  isFocus.value = true
  emit('focus', textareaDom.value?.value)
}

/**
 * textarea失焦回调
 */
const inputBlur = () => {
  isFocus.value = false
  emit('blur', textareaDom.value?.value)
}
</script>

<style lang="scss" scoped>
@import './style.scss';
@import url('../../css/comment/animate.css');
</style>
